package cn.yto.print.controller;

import cn.yto.print.config.CustomWindowEvent;
import cn.yto.print.config.ThreadPoolManager;
import cn.yto.print.config.i18n.LocaleChangeEvent;
import cn.yto.print.enums.PrintStatusEnum;
import cn.yto.print.model.dto.PrintHistoryDTO;
import cn.yto.print.model.request.HistoryQueryRequest;
import cn.yto.print.model.response.PageResponse;
import cn.yto.print.sqlite.service.IPrintHistoryService;
import de.felixroske.jfxsupport.FXMLController;
import de.felixroske.jfxsupport.GUIState;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Task;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;

import java.net.URL;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.Map;
import java.util.ResourceBundle;

@Slf4j
@FXMLController
public class HistoryController extends BaseController implements Initializable {

    private final Map<String, Integer> printStatusMap = new HashMap<>();

    private static final int DEFAULT_PAGE_SIZE = 20;

    @FXML
    public Label waybillNoLabel;
    @FXML
    public TextField waybillNoText;
    @FXML
    public Label printStatusLabel;
    @FXML
    public ComboBox<String> printStatusBox;
    @FXML
    public Label printDateLabel;
    @FXML
    public Label toLable;
    @FXML
    public DatePicker startDatePicker;
    @FXML
    public DatePicker endDatePicker;
    @FXML
    public Button resetButton;
    @FXML
    public Button queryButton;
    @FXML
    public TableView<PrintHistoryDTO> historyTable;
    @FXML
    public Label countLabel;
    @FXML
    public Label eveyPageLabel;
    @FXML
    public ComboBox<Integer> pageSizeBox;
    @FXML
    public Button firstPageBtn;
    @FXML
    public Button prevPageBtn;
    @FXML
    public Label pageInfoLabel;
    @FXML
    public Button nextPageBtn;
    @FXML
    public Button lastPageBtn;
    @FXML
    public TableColumn<PrintHistoryDTO, Void> indexColumn;
    @FXML
    public TableColumn<PrintHistoryDTO, String> documentIdColumn;
    @FXML
    public TableColumn<PrintHistoryDTO, String> expressTypeColumn;
    @FXML
    public TableColumn<PrintHistoryDTO, String> printerColumn;
    @FXML
    public TableColumn<PrintHistoryDTO, String> waybillNoColumn;
    @FXML
    public TableColumn<PrintHistoryDTO, String> printStatusColumn;
    @FXML
    public TableColumn<PrintHistoryDTO, String> createTimeColumn;

    @Autowired
    private IPrintHistoryService printHistoryService;

    private int totalPages = 0;
    private int currentPage = 1;
    private long totalNum = 0L;
    private int pageSize = DEFAULT_PAGE_SIZE;

    @Override
    public void initialize(URL location, ResourceBundle resources) {

        waybillNoLabel.textProperty().bind(I18N.getStringBinding("print.history.waybillNo"));
        waybillNoText.setPromptText(I18N.get("print.waybillNo.prompt"));
        printStatusLabel.textProperty().bind(I18N.getStringBinding("print.history.printStatus"));
        printDateLabel.textProperty().bind(I18N.getStringBinding("print.history.printDate"));
        startDatePicker.setPromptText(I18N.get("print.history.startDate"));
        toLable.textProperty().bind(I18N.getStringBinding("print.history.toshow"));
        endDatePicker.setPromptText(I18N.get("print.history.endDate"));
        resetButton.textProperty().bind(I18N.getStringBinding("print.history.resetButton"));
        queryButton.textProperty().bind(I18N.getStringBinding("print.history.queryButton"));
        indexColumn.textProperty().bind(I18N.getStringBinding("print.history.indexColumn"));
        documentIdColumn.textProperty().bind(I18N.getStringBinding("print.history.documentId"));
        expressTypeColumn.textProperty().bind(I18N.getStringBinding("print.history.expressType"));
        printerColumn.textProperty().bind(I18N.getStringBinding("print.history.printerText"));
        waybillNoColumn.textProperty().bind(I18N.getStringBinding("print.history.waybillNoText"));
        printStatusColumn.textProperty().bind(I18N.getStringBinding("print.history.printStatusText"));
        createTimeColumn.textProperty().bind(I18N.getStringBinding("print.history.createTime"));
        eveyPageLabel.textProperty().bind(I18N.getStringBinding("print.history.eveyPage"));
        firstPageBtn.textProperty().bind(I18N.getStringBinding("print.history.firstPage"));
        prevPageBtn.textProperty().bind(I18N.getStringBinding("print.history.prevPage"));
        nextPageBtn.textProperty().bind(I18N.getStringBinding("print.history.nextPage"));
        lastPageBtn.textProperty().bind(I18N.getStringBinding("print.history.lastPage"));

        Platform.runLater(() -> {
            Integer selectedStatus = printStatusMap.get(printStatusBox.getValue());
            // 清空下拉列表选择和选项
            printStatusBox.setValue(null);
            printStatusBox.getItems().clear();
            printStatusMap.clear();
            for (PrintStatusEnum status : PrintStatusEnum.values()) {
                printStatusMap.put(I18N.get(status.getLocale()), status.getStatus());
            }
            printStatusBox.getItems().addAll(printStatusMap.keySet());
            if (selectedStatus != null) {
                printStatusMap.forEach((key, value) -> {
                    if (value.equals(selectedStatus)) {
                        printStatusBox.setValue(key);
                    }
                });
            }
        });

        pageSizeBox.setValue(DEFAULT_PAGE_SIZE);
        pageSizeBox.valueProperty().addListener((obs, oldVal, newVal) -> {
            if (newVal != null && !newVal.equals(oldVal)) {
                handlePageSizeChange(newVal);
            }
        });
        // 初始化按钮事件
        firstPageBtn.setOnAction(e -> navigateToFirstPage());
        prevPageBtn.setOnAction(e -> navigateToPreviousPage());
        nextPageBtn.setOnAction(e -> navigateToNextPage());
        lastPageBtn.setOnAction(e -> navigateToLastPage());
        queryButton.setOnAction(e -> refreshData());
        resetButton.setOnAction(e -> handleReset());

        indexColumn.setCellFactory(column -> new TableCell<PrintHistoryDTO, Void>() {
            @Override
            protected void updateItem(Void item, boolean empty) {
                super.updateItem(item, empty);
                setText(empty ? null : String.valueOf(calculateSerialNumber()));
            }

            private int calculateSerialNumber() {
                return (currentPage - 1) * pageSize + getIndex() + 1;
            }
        });
        indexColumn.setCellValueFactory(null);
        historyTable.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);

        GUIState.getStage().addEventHandler(CustomWindowEvent.CLEAR_CACHE, event -> {
            clearPrintHistory();
        });

        LocalDate thirtyDaysAgo = LocalDate.now().minusDays(30);
        LocalDate today = LocalDate.now();
        startDatePicker.setDayCellFactory(picker -> createDateCell(thirtyDaysAgo, today, null));
        initEndDateCellFactory(thirtyDaysAgo, today);
        startDatePicker.valueProperty().addListener((obs, oldVal, newVal) -> {
            // 清空结束日期
            endDatePicker.setValue(null);
            initEndDateCellFactory(thirtyDaysAgo, today);
        });

        initEnterKeyQuerySupport();
        refreshData();
    }

    private DateCell createDateCell(LocalDate minDate, LocalDate maxDate, LocalDate startDate) {
        return new DateCell() {
            @Override
            public void updateItem(LocalDate date, boolean empty) {
                super.updateItem(date, empty);
                boolean isDisabled = empty || date.isBefore(minDate) || date.isAfter(maxDate);
                if (startDate != null && date.isBefore(startDate)) {
                    isDisabled = true;
                }
                setDisable(isDisabled);
                if (isDisabled) {
                    setStyle("-fx-background-color: #eeeeee; -fx-text-fill: #999999;");
                } else {
                    setStyle("");
                }
            }
        };
    }

    /**
     * 初始化结束日期的单元格
     */
    private void initEndDateCellFactory(LocalDate thirtyDaysAgo, LocalDate today) {
        LocalDate currentStartDate = startDatePicker.getValue();
        endDatePicker.setDayCellFactory(picker -> createDateCell(thirtyDaysAgo, today, currentStartDate));
    }

    /**
     * 初始化回车键查询支持
     */
    private void initEnterKeyQuerySupport() {
        queryButton.setDefaultButton(true);
    }

    /**
     * 重置查询条件和分页
     */
    public void handleReset() {
        waybillNoText.clear();
        printStatusBox.setValue(null);
        startDatePicker.setValue(null);
        endDatePicker.setValue(null);
        resetPagination();
        refreshData();
    }

    private HistoryQueryRequest buildQueryRequest() {
        HistoryQueryRequest request = new HistoryQueryRequest();
        request.setWaybillNo(StringUtils.trimToNull(waybillNoText.getText()));
        request.setPrintStatus(printStatusMap.get(printStatusBox.getValue()));
        LocalDate startDate = startDatePicker.getValue();
        LocalDate endDate = endDatePicker.getValue();
        LocalDate thirtyDaysAgo = LocalDate.now().minusDays(30);
        if (startDate != null && startDate.isBefore(thirtyDaysAgo)) {
            startDate = thirtyDaysAgo;
            startDatePicker.setValue(startDate);
        }
        if (endDate != null) {
            if (endDate.isBefore(thirtyDaysAgo)) {
                endDatePicker.setValue(null);
            } else if (startDate != null && endDate.isBefore(startDate)) {
                endDate = startDate;
                endDatePicker.setValue(endDate);
            }
        }
        request.setStartTime(startDatePicker.getValue());
        request.setEndTime(endDatePicker.getValue());
        return request;
    }

    public void refreshData() {
        Task<ObservableList<PrintHistoryDTO>> queryTask = new Task<ObservableList<PrintHistoryDTO>>() {
            @Override
            protected ObservableList<PrintHistoryDTO> call() {
                try {
                    HistoryQueryRequest query = buildQueryRequest();
                    PageResponse<PrintHistoryDTO> response = printHistoryService.queryByPage(query, currentPage, pageSize);
                    totalNum = response.getTotal();
                    totalPages = response.getTotalPages();
                    return FXCollections.observableArrayList(response.getList());
                } catch (Exception e) {
                    log.error("查询打印历史记录异常", e);
                    return FXCollections.observableArrayList();
                }
            }
        };

        queryTask.setOnSucceeded(e -> {
            historyTable.setItems(queryTask.getValue());
            updatePaginationStatus();
            countLabel.setText(String.format(I18N.get("print.history.totalNum"), totalNum));
        });
        ThreadPoolManager.getExecutorService().submit(queryTask);
    }

    private void handlePageSizeChange(int newPageSize) {
        if (newPageSize != pageSize) {
            this.pageSize = newPageSize;
            resetToFirstPage();
            refreshData();
        }
    }

    public void navigateToFirstPage() {
        if (currentPage != 1) {
            currentPage = 1;
            refreshData();
        }
    }

    public void navigateToPreviousPage() {
        if (currentPage > 1) {
            currentPage--;
            refreshData();
        }
    }

    public void navigateToNextPage() {
        if (currentPage < totalPages) {
            currentPage++;
            refreshData();
        }
    }
    public void navigateToLastPage() {
        if (currentPage != totalPages && totalPages > 0) {
            currentPage = totalPages;
            refreshData();
        }
    }

    private void updatePaginationStatus() {
        // 更新页码显示
        currentPage = Math.max(1, Math.min(currentPage, totalPages));
        pageInfoLabel.setText(String.format(I18N.get("print.history.currentPage"), currentPage, totalPages));
        boolean isFirstPage = currentPage == 1;
        boolean isLastPage = currentPage == totalPages || totalPages == 0;
        firstPageBtn.setDisable(isFirstPage);
        prevPageBtn.setDisable(isFirstPage);
        nextPageBtn.setDisable(isLastPage);
        lastPageBtn.setDisable(isLastPage);
    }

    private void resetPagination() {
        currentPage = 1;
        totalPages = 0;
        totalNum = 0L;
        updatePaginationStatus();
    }

    private void resetToFirstPage() {
        currentPage = 1;
        updatePaginationStatus();
    }

    @EventListener
    public void updateLocaleEvent(LocaleChangeEvent event) {
        Platform.runLater(() -> {
            if (null != waybillNoText && null != startDatePicker) {
                waybillNoText.setPromptText(I18N.get("print.waybillNo.prompt"));
                startDatePicker.setPromptText(I18N.get("print.history.startDate"));
                endDatePicker.setPromptText(I18N.get("print.history.endDate"));
                countLabel.setText(String.format(I18N.get("print.history.totalNum"), totalNum));
                pageInfoLabel.setText(String.format(I18N.get("print.history.currentPage"), currentPage, totalPages));
                Platform.runLater(() -> {
                    Integer selectedStatus = printStatusMap.get(printStatusBox.getValue());
                    printStatusBox.setValue(null);
                    printStatusBox.getItems().clear();
                    printStatusMap.clear();
                    for (PrintStatusEnum status : PrintStatusEnum.values()) {
                        printStatusMap.put(I18N.get(status.getLocale()), status.getStatus());
                    }
                    printStatusBox.getItems().addAll(printStatusMap.keySet());
                    if (selectedStatus != null) {
                        printStatusMap.forEach((key, value) -> {
                            if (value.equals(selectedStatus)) {
                                printStatusBox.setValue(key);
                            }
                        });
                    }
                });
            }
        });
    }

    private void clearPrintHistory() {
        printHistoryService.clearPrintHistory();
        refreshData();
    }

}
